﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Prometheus;

namespace Helpers
{
    public class PrometheusHelperStartupFilter : IStartupFilter
    {
        public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
        {
            return app =>
            {
                try
                {
                    var env = app.ApplicationServices.GetService<IWebHostEnvironment>();
                    var options = app.ApplicationServices.GetRequiredService<PrometheusHelperOptions>();
                    if (options.IsStartMetricPusher)
                    {
                        if (options.MetricPusherOptions == null) throw new ArgumentNullException(nameof(options.MetricPusherOptions));
                        options.MetricPusherOptions.Job ??= AppDomain.CurrentDomain.FriendlyName;
                        MetricPusher metricPusher = null;
                        if (metricPusher == null)
                        {
                            //var features = app.Properties["server.Features"] as FeatureCollection;
                            var features = app.ServerFeatures;
                            var port = Regex.Match(features.Get<IServerAddressesFeature>()
                                .Addresses
                                .FirstOrDefault() ?? "", @":(\d+)").Groups[1].Value;

                            string ip = null;
                            try
                            {
                                if (env != null && !env.IsDevelopment())
                                {
                                    //ip = (await IpHelper.GetRemoteIp().ConfigureAwait(false)).Ip;

                                    using var client = new HttpClient();
                                    client.Timeout = TimeSpan.FromSeconds(5);
                                    ip = client.GetStringAsync(options.IpParserUrl).GetAwaiter().GetResult();
                                }
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine($"获取ip异常,{ex.Message}");
                            }
                            if (string.IsNullOrWhiteSpace(ip))
                            {
                                //NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces(); //适配器
                                ip = IpHelper.GetLocalIp().Ip;
                            }

                            var address = $"{ip}:{port}";

                            if (string.IsNullOrWhiteSpace(options.MetricPusherOptions.Instance))
                            {
                                options.MetricPusherOptions.Instance = address;
                            }
                            else
                            {
                                List<Tuple<string, string>> list = options.MetricPusherOptions.AdditionalLabels == null ? new List<Tuple<string, string>>() : new List<Tuple<string, string>>(options.MetricPusherOptions.AdditionalLabels);
                                if (!options.MetricPusherOptions.AdditionalLabels.Any(x => x.Item1 == "ip"))
                                {
                                    list.Add(new Tuple<string, string>("ip", address));
                                }
                                if (env != null)
                                { 
                                    list.Add(new Tuple<string, string>("env", env.EnvironmentName));
                                }
                                options.MetricPusherOptions.AdditionalLabels = list;
                            }
                            metricPusher = new MetricPusher(options.MetricPusherOptions);
                            metricPusher.Start();
                            Console.WriteLine($"start MetricPusher {address}");
                        }
                    }
                    if (options.IsUseHttpMetrics)
                    {
                        app.UseHttpMetrics();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("UseMetricPusherHelper异常--" + ex.ToString());
                }
                next(app);
            };
        }
    }
}
